package plgwsmsg

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/gohttp"
	"dgo/goutils/utils"
	"dgo/plg/plgbase"
	"gitee.com/ymofen/gobase/gotask"
	"gitee.com/ymofen/supervalue"
	"golang.org/x/net/websocket"
	"net/http"
	"strings"
	"time"
)

type PlgWsMsgServer struct {
	plgbase.PlgBase
	// 0:都显示, 1:显示>=1的消息
	msgShowLvl int8
	msglst     *utils.SyncCycleList
	serviceUrl string

	msgServType string

	sendMonitor *utils.MonitorSpeedSizeRec
	recvMonitor *utils.MonitorSpeedSizeRec

	wsserv         *WsMsgServ
	HandleConnFunc func(wsconn *websocket.Conn)
}

func (this *PlgWsMsgServer) HandleWsConn(wsconn *websocket.Conn) {
	this.HandleConnFunc(wsconn)
}

func (this *PlgWsMsgServer) initWsServer() {
	this.HandleConnFunc = this.wsserv.HandleWsConn
	this.wsserv.OnDisconnected = func(conn *WsClientConn, reason string) {
		if strings.HasPrefix(reason, "[err]") {
			this.LogWarnMessage(2, "%s, %s, from:%s", reason, conn.SessionId, conn.RemoteAddr)
		}
	}
	this.wsserv.OnSent = func(conn *WsClientConn, buf []byte) {
		this.sendMonitor.DeltaBuf(buf)
	}

	this.wsserv.OnRecv = func(conn *WsClientConn, buf []byte) {
		this.recvMonitor.DeltaBuf(buf)
	}

}

/*
		{
		  "id": "xxx",
		  "type": "plgs.ws.msgserv",
		  "conf": {
	        "msgservType":"binmsg",
		  }
		}
*/
func (this *PlgWsMsgServer) ReloadConf(conf *wrapper.SuperValue) error {
	if conf == nil {
		return nil
	}

	if this.msglst == nil {
		this.msglst = utils.NewSyncCycleList()
		this.msgShowLvl = 2
	}

	if this.recvMonitor == nil {
		this.recvMonitor = utils.NewMonitorSpeedSizeRec()
		this.sendMonitor = utils.NewMonitorSpeedSizeRec()
		utils.Monitor.AddMonitor(this.recvMonitor)
		utils.Monitor.AddMonitor(this.sendMonitor)
	}

	str := conf.StringByName("msgservType", "jsonmsg")
	if str != this.msgServType {
		if this.wsserv != nil {
			this.wsserv.Close()
		}
		if str == "binmsg" {
			this.wsserv = NewBinMsgServ(this.PlugId)
		} else {
			this.wsserv = NewJsonMsgServ(this.PlugId)
		}
		this.initWsServer()
	}
	if this.wsserv == nil {
		this.wsserv = NewJsonMsgServ(this.PlugId)
		this.initWsServer()
	}

	this.ConfigServiceURL(conf.StringByName("serviceurl", ""))

	this.msgShowLvl = conf.Int8ByName("msgshowlvl", this.msgShowLvl)

	gotask.DefaultPatrolTask().AddTask(this.PlugId, time.Second*30, func(id interface{}, args ...interface{}) {
		//utils.DefaultWorkers().PostTaskFunc(this, this.innerWork)
	})
	return nil
}

func (this *PlgWsMsgServer) Close() (err error) {
	this.wsserv.Close()
	this.PlgBase.Close()
	utils.Monitor.RemoveMonitorRec(this.recvMonitor)
	utils.Monitor.RemoveMonitorRec(this.sendMonitor)
	gotask.DefaultPatrolTask().DelTask(this.PlugId)
	return
}

func (this *PlgWsMsgServer) DoStatusRequestRequest(args ...interface{}) (resp interface{}) {
	reqArgs, _ := plgbase.NewSVArgs(true, args...)
	if reqArgs != nil {
		defer reqArgs.Clear()
		itype := reqArgs.IntByName("type", 0)
		if itype == 99 {
			json := wrapper.NewSVObjectCache(true)
			json.SetKeyValue("online", this.wsserv.Online())
			json.SetKeyValue("status", this.wsserv.StatusText())
			json.SetKeyValue("recv", this.recvMonitor.Info())
			json.SetKeyValue("send", this.sendMonitor.Info())
			json.SetKeyValue("msgShowLvl", this.msgShowLvl)
			json.SetKeyValues("now", utils.NowString())
			return json
		} else if itype == 98 {
			return this.msglst
		} else if itype == 97 {
			lvl := int8(reqArgs.IntByName("lvl", -1))
			if lvl != -1 {
				this.msgShowLvl = lvl
			}
			return utils.BuildJSONString("code", 0, "lvl", this.msgShowLvl)
		} else if itype == 1 {
			json := wrapper.NewSVArrayCache(true)
			return json
		} else {
		}
	}
	var sb utils.BytesBuilder
	PrjHttpUtils.AppendIndexBody(&sb, "status", "status?type=99")
	PrjHttpUtils.AppendIndexBody(&sb, "msglist", "status?type=98&n=100&searchval=")
	PrjHttpUtils.AppendIndexBody(&sb, "msgshowlvl", "status?type=97&lvl=")
	PrjHttpUtils.AppendIndexBody(&sb, "lst", "status?type=1&n=100&searchval=")
	return sb.Bytes()
}

func (this *PlgWsMsgServer) ConfigServiceURL(strv string) {
	if this.serviceUrl != strv {
		if len(this.serviceUrl) > 0 {
			gohttp.UnHandle(this.serviceUrl)
			this.LogInfoMessage(2, "服务停止:%s", this.serviceUrl)
		}
		this.serviceUrl = strv
		if len(this.serviceUrl) > 0 {
			wshd := websocket.Server{
				Handshake: func(config *websocket.Config, req *http.Request) (err error) {
					config.Origin, err = websocket.Origin(config, req)
					return nil // Origin 非法时不断开
				},
				Handler: this.wsserv.HandleWsConn,
			}
			//wshd := websocket.Handler(this.onHttpHandle)
			gohttp.Handle(this.serviceUrl, wshd)
			this.LogInfoMessage(2, "服务启动:%s", this.serviceUrl)
		}
	}
}

/*
msglvl: 值越大信息约重要
*/
func (this *PlgWsMsgServer) LogInfoMessage(msglvl int8, s string, args ...interface{}) {
	if msglvl < this.msgShowLvl {
		return
	}
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_INFO, 1, s, args...)
}

func (this *PlgWsMsgServer) LogWarnMessage(msglvl int8, s string, args ...interface{}) {
	if msglvl < this.msgShowLvl {
		return
	}
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_WARN, 1, s, args...)
}

func CreatePlgWsMsgServerFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &PlgWsMsgServer{}

	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}

func init() {
	utils.RegisterCreate("plgs.ws.msgserv", CreatePlgWsMsgServerFunc)
}
